/**
 * @constructor
 * @param {File} file
 * @param {Function} fileLoadedCallback
 * @return {MowerFileInputReader}
 */
function MowerFileInputReader(file, fileLoadedCallback) {
	this.lines;
	this.currentLineNumber = 0;
	this.currentCharacterNumber = 0;	
	this.currentMowerCommandsEndCallback = function() {};
	this.mowersEndedCallback = function() {};
	
	if(file != null) {
		var self = this;	
		var fileReader = new FileReader();
		fileReader.onload = function(theFile)  {
	    	var contents = theFile.target.result;
	        self.lines = contents.split(/\r\n|\r|\n/g);
	        fileLoadedCallback();
	    };
		fileReader.readAsText(file);
	}
};

/**
 * @public
 * @throws {MissingLawnCornerException|UnparsableLawnCornerException}
 * @returns {Position}
 */
MowerFileInputReader.prototype.getLawnCorner = function() {
	if(this.lines.length == 0) {
		throw new MissingLawnCornerError("");
	}
	var line = this.lines[this.currentLineNumber++];
	try {
		this.validateLawnCornerLine(line);
	} catch(e) {
		throw new MissingLawnCornerException("File doesn't contain line for lawn upper-right corner!");
	}
	var position = null;
	try {
		var position = this.parseLawnCornerLine(line);
	} catch(e) {
		throw new UnparsableLawnCornerException("Unable to parse lawn upper-right corner line: " + line);
	}
	return position;
};

/**
 * @public
 * @throws {UnparsableMowerStartVectorException}
 * @returns {MowerVector}
 */
MowerFileInputReader.prototype.nextStartVector = function() {
	this.advanceToNextMowerStartVectorLine();
	if(this.currentLineNumber >= this.lines.length) {
		this.mowersEndedCallback();
		return null;
	}
	var line = this.lines[this.currentLineNumber++];
	this.currentCharacterNumber = 0;
	
	var mowerVector = null;
	try {
		var mowerVector = this.parseStartVectorLine(line);
	} catch(e) {
		throw new UnparsableMowerStartVectorException("Unparsable mower start vector line on #" + this.currentLineNumber + ": " + line);
	}	
	return mowerVector;
};

/**
 * @public
 * @throws {UnparsableCommandException}
 * @returns {COMMAND}
 */
MowerFileInputReader.prototype.nextCommand = function() {
	this.advanceToNextCommandsLine();
	var line = this.lines[this.currentLineNumber];
	if(this.currentCharacterNumber >= line.length) {
		this.currentMowerCommandsEndCallback();
		return null;
	}
	
	var char = line.charAt(this.currentCharacterNumber++);	
		
	var command = null;
	try {
		command = this.parseCommandChar(char);
	} catch(e) {
		throw new UnparsableCommandException("Unable to parse command from character: " + char + " (line #" + this.currentLineNumber + ", character #" + this.currentCharacterNumber + ")");
	}
	
	return command;	
};

/**
 * @public
 * @param {Function} callback
 */
MowerFileInputReader.prototype.setCurrentMowerCommandsEndCallback = function(callback) {
	this.currentMowerCommandsEndCallback = callback;
};

/**
 * @public
 * @param {Function} callback
 */
MowerFileInputReader.prototype.setMowersEndedCallback = function(callback) {
	this.mowersEndedCallback = callback;
};

/**
 * @private
 */
MowerFileInputReader.prototype.advanceToNextMowerStartVectorLine = function() {
	if(this.currentLineNumber % 2 == 0) {
		this.currentLineNumber++;
	}
};

/**
 * @private
 */
MowerFileInputReader.prototype.advanceToNextCommandsLine = function() {
	if(this.currentLineNumber % 2 != 0) {
		this.currentLineNumber++;
	}
};

/**
 * @private
 * @throws {MOWER_INPUT_FILE_READER_ERRORS.MissingLineError}
 * @param {string} line
 */
MowerFileInputReader.prototype.validateLawnCornerLine = function(line) {
	if(!line || line == "" || line == null) {
		throw new MissingLineException("");
	}	
};

/**
 * 
 * @param {string} line
 * @throws {MOWER_INPUT_FILE_READER_ERRORS.UnparsableLineError}
 * @returns {Position}
 */
MowerFileInputReader.prototype.parseLawnCornerLine = function(line) {
	var lineArr = line.split(" ");
	if(lineArr.length != 2) {
		throw new UnparsableLineException("");
	}
	var x = parseInt(lineArr[0]);	
	if(isNaN(x)) {
		throw new UnparsableLineException("");
	}
	var y = parseInt(lineArr[1]);	
	if(isNaN(y)) {
		throw new UnparsableLineException("");
	}
	
	return new Position(x, y);
	
};

/**
 * @private
 * @param {string} line
 * @returns {MowerVector}
 */
MowerFileInputReader.prototype.parseStartVectorLine = function(line) {
	var lineArr = line.split(" ");
	if(lineArr.length != 3) {
		throw new UnparsableLineException("");
	}
	var x = parseInt(lineArr[0]);	
	if(isNaN(x)) {
		throw new UnparsableLineException("");
	}
	var y = parseInt(lineArr[1]);	
	if(isNaN(y)) {
		throw new UnparsableLineException("");
	}
	if(!DIRECTION.hasOwnProperty(lineArr[2])) {
		throw new UnparsableLineException("");
	}
	
	return new MowerVector(new Position(x, y), DIRECTION[lineArr[2]]);
};

/**
 * @private
 * @param {string} char
 * @returns {COMMAND}
 */
MowerFileInputReader.prototype.parseCommandChar = function(char) {
	if(!COMMAND.hasOwnProperty(char)) {
		throw new UnparsableCharacterException("");
	}
	return COMMAND[char];
};